package com.vhall.component.framework.oss.client.impl;

import cn.hutool.core.io.FileUtil;
import com.vhall.component.framework.oss.client.OssClient;
import com.vhall.component.framework.oss.client.OssCodeMapping;
import com.vhall.component.framework.oss.client.OssResult;
import com.vhall.component.framework.oss.properties.OssProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;

/**
 * 云存储抽象类
 *
 * @author yongzheng.xu
 * @date 2021/5/22 20:44
 */
@Slf4j
public abstract class AbstractOssClient implements OssClient {

    /**
     * 配置信息
     */
    protected volatile OssProperties properties;

    /**
     * 错误码枚举类
     */
    protected final OssCodeMapping codeMapping;


    protected AbstractOssClient(OssProperties properties, OssCodeMapping codeMapping) {
        this.codeMapping = codeMapping;
        this.properties = properties;
    }

    /**
     * 自定义初始化
     */
    protected abstract void doInit();

    /**
     * 初始化
     */
    public final void init() {
        doInit();
        log.info("[init][{} OSS Client 初始化完成]", this.properties.getName());
    }

    /**
     * 刷新配置文件
     *
     * @param properties
     */
    public final void refresh(OssProperties properties) {
        // 判断是否更新
        if (properties.equals(this.properties)) {
            return;
        }
        log.info("[refresh][OSS Client 配置发生变化，重新初始化]");
        this.properties = properties;

        // 初始化
        this.init();
    }

    /**
     * 上传文件
     *
     * @param name        文件名称
     * @param contentType 文件类型
     * @param stream      输入流
     * @return
     */
    @Override
    public final OssResult<String> upload(String name, String contentType, InputStream stream) {
        OssResult<String> result;
        try {
            result = doUpload(name, contentType, stream);
        } catch (Exception e) {
            // 打印异常日志
            log.error("[upload][文件上传异常，name:[{}]]", name, e);
            // 封装返回
            return OssResult.error((Throwable) e);
        }
        return result;
    }

    /**
     * 上传文件
     *
     * @param file
     * @return
     */
    @Override
    public final OssResult<String> upload(File file) {
        OssResult<String> result;
        try {
            String mimeT = FileUtil.getMimeType(file.getName());
            result = doUpload(file.getName(), mimeT, new ByteArrayInputStream(FileUtil.readBytes(file)));
        } catch (Exception ex) {
            // 打印异常日志
            log.error("[upload][文件上传异常]", ex);
            // 封装返回
            return OssResult.error((Throwable) ex);
        }
        return result;
    }

    /**
     * 上传文件
     *
     * @param file
     * @return
     */
    @Override
    public final OssResult<String> upload(MultipartFile file) {
        OssResult<String> result;
        try {
            result = doUpload(file.getOriginalFilename(), file.getContentType(), new ByteArrayInputStream(file.getBytes()));
        } catch (Exception ex) {
            // 打印异常日志
            log.error("[upload][文件上传异常]", ex);
            // 封装返回
            return OssResult.error((Throwable) ex);
        }
        return result;
    }

    /**
     * 执行上传动作
     *
     * @param name        文件名字
     * @param contentType 文件类型
     * @param stream      输入流
     * @return
     * @throws IOException
     */
    protected abstract OssResult<String> doUpload(String name, String contentType, InputStream stream) throws IOException;
}
